home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 2 / MacMania 2.toast / Demo's / Music⁄Sounds / BeepSay 1.0.1 / Preferences.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-22  |  11.5 KB  |  465 lines  |  [TEXT/MPS ]

  1. /******************************************************************************
  2. **
  3. **  Folder Name:    BS
  4. **     File Name:    Preferences.c
  5. **
  6. **   Copyright:    © 1993 by Siren Enterprises, all rights reserved.
  7. **
  8. **   Description:    Support Routines for Lil´ BeepSay Preferences
  9. **
  10. *******************************************************************************
  11. **                       A U T H O R   I D E N T I T Y
  12. *******************************************************************************
  13. **
  14. **    Initials    Name
  15. **    --------    -----------------------------------------------
  16. **    kw            Ken Wieschhoff
  17. **
  18. *******************************************************************************
  19. **                      R E V I S I O N   H I S T O R Y
  20. *******************************************************************************
  21. **
  22. **      Date        Time    Author    Description
  23. **    --------    -----    ------    ---------------------------------------------
  24. **    06/22/93    15:54    kw        1+ Add animate lips option
  25. **    05/17/93    21:02    kw        Original version
  26. **
  27. ******************************************************************************/
  28.  
  29. #include    <OSUtils.h>
  30. #include    <Files.h>
  31. #include    <Types.h>
  32. #include    <Resources.h>
  33. #include    <script.h>
  34. #include    <GestaltEqu.h>
  35. #include    <traps.h>
  36. #include    <errors.h>
  37. #include    <PLStringFuncs.h>
  38. #include    <Folders.h>
  39. #include    <Packages.h>
  40. #include    "Utilities.h"
  41. #include    "Preferences.h"
  42.  
  43. extern pascal void ShowStr( StringPtr str);
  44. extern pascal void ShowStrNum( StringPtr str, OSErr err);
  45.  
  46. #define BTstQ(arg, bitnbr)        (arg & (1 << bitnbr))
  47.  
  48.  
  49. //••••••••••••••••••••••••••••••••••••••••••••••••
  50. //••••••••••• Preferences routines••••••••••••••••
  51. //••••••••••••••••••••••••••••••••••••••••••••••••
  52. pascal OSErr GetPreferencesFileName(FSSpec *aSpec, Str31 filename)
  53. {
  54.     OSErr             err;
  55.     long            gestaltResult;
  56.     SysEnvRec        theWorld;
  57.     WDPBRec         wdirpb;
  58.     unsigned char     volName[34];
  59.     FSSpec            newFolderSpec;
  60.  
  61.     // Check that the Gestalt trap exists.  If this is a 6.0.7 system, Gestalt
  62.     // will be added via a system extension.  If the extension is off,  executing 
  63.     // Gestalt will cause an unimplemented trap instruction.
  64.     // _Gestalt, _GestaltDispatch is 0xA0AD
  65.     if (NGetTrapAddress(0xA0AD, GetTrapType(0xA0AD)) ==
  66.             NGetTrapAddress(_Unimplemented, GetTrapType(_Unimplemented)) )             
  67.         return unimpErr;
  68.  
  69.     // Check that the FindFolder trap is present.
  70.     err = Gestalt(gestaltFindFolderAttr, &gestaltResult);
  71.  
  72.     // Check that the Folder Manager is available.  If not use the system folder.
  73.     if (err == noErr && ( BTstQ (gestaltResult, gestaltFindFolderPresent)) ) {
  74.     
  75.     
  76.         // Find the FSSpec of the Preferences Folder within the System Folder.
  77.         err = FindFolder(kOnSystemDisk, kPreferencesFolderType,
  78.                     kCreateFolder, &aSpec->vRefNum, &aSpec->parID);
  79.         if ( err != noErr) {
  80.             return ( err);
  81.         }
  82.     
  83.         err = FSMakeFSSpec( aSpec->vRefNum, aSpec->parID, filename, &newFolderSpec);
  84.         if ( err != fnfErr) {
  85.             if (err != noErr) {
  86.                 return ( err);
  87.             }
  88.         }
  89.         *aSpec = newFolderSpec;
  90.     }
  91.     else {
  92.         err = SysEnvirons( 2, &theWorld);
  93.         if (err != noErr)
  94.             return (err);
  95.             
  96.         // Get volume reference number and dirID of the system file 
  97.         zeroMemory((Ptr)&wdirpb, sizeof(WDPBRec));
  98.         wdirpb.ioVRefNum = theWorld.sysVRefNum;
  99.         volName[0] = '\000';
  100.         wdirpb.ioNamePtr = volName;
  101.         err = PBGetWDInfo(&wdirpb, 0);
  102.         if (err != noErr)
  103.             return (err);
  104.         aSpec->vRefNum = wdirpb.ioWDVRefNum;
  105.         aSpec->parID = wdirpb.ioWDDirID;
  106.         PLstrcpy(aSpec->name, filename);
  107.     }
  108.  
  109.  
  110.     return (noErr);
  111. }
  112.  
  113. pascal OSErr WriteToPrefs(PreferencesHdl prefHdl, Str31 filename)
  114. {
  115.     long                    count;
  116.     short                    dRefNum;
  117.     FSSpec                    aSpec;
  118.     OSErr                    err;
  119.     short                    versionNumber;
  120.  
  121.     // Get the preferences file name from disk.
  122.     err = GetPreferencesFileName( &aSpec, filename);
  123.     if ( err != noErr)
  124.         return ( err);
  125.         
  126.     
  127.     // Delete the preferences file unconditionally.  Don't flag an error
  128.     // if it isn't there.
  129.     err = xFSpDelete(&aSpec);
  130.     
  131.     // Ignore file-not-found errors; we may be creating it for the first time.
  132.     if (( err != noErr) && ( err != fnfErr))  {
  133.         ShowStrNum( "\pFSpDelete error deleting old preferences file", err);
  134.         return ( err);
  135.     }
  136.  
  137.     // Create a new preferences file.
  138.     err = xFSpCreateResFile(&aSpec, kBeepSaySignature, 'Pref', smSystemScript);
  139.     if ( err != noErr)  {
  140.         ShowStrNum("\pFSpCreateResFile error creating a new preferences file ", err);
  141.         return ( err);
  142.     }
  143.  
  144.     // Open the data fork of the new preferences.
  145.     err = xFSpOpenDF(&aSpec, fsWrPerm, &dRefNum);
  146.  
  147.     if (err != noErr)  {
  148.         ShowStrNum("\pFS(p)Open(DF) error opening a new preferences file ", err);
  149.         return ( err);
  150.     }
  151.  
  152.     // Write the version number of the file.
  153.     versionNumber = kCurrentVersion;
  154.     count = sizeof(versionNumber);
  155.     err =  FSWrite(dRefNum, &count, &versionNumber);
  156.     if (err != noErr) {
  157.         ShowStrNum("\pFSWrite error writing version number ", err);
  158.         goto errExit;
  159.     }
  160.  
  161.     if (count != sizeof( versionNumber)) {
  162.         ShowStrNum("\pFSWrite error writing version. Incorrect count (should be 2)", count);
  163.         err = (-1);
  164.         goto errExit;
  165.     }
  166.  
  167.     HLock( (Handle) prefHdl);
  168.     // Write the Preferences structure to disk.
  169.     count = sizeof(struct Preferences);
  170.     err =  FSWrite(dRefNum, &count, (Ptr) *prefHdl);
  171.     if (err != noErr) {
  172.         ShowStrNum("\pFSWrite error writing version number ", err);
  173.         goto errExit;
  174.     }
  175.  
  176.     if (count != sizeof( struct Preferences)) {
  177.         ShowStrNum("\pFSWrite error writing data. Count should be", sizeof(struct Preferences));
  178.         ShowStrNum("\pCount is: ", count);
  179.         err = (-1);
  180.         goto errExit;
  181.     }
  182.     
  183.  
  184. errExit:    
  185.  
  186.     HUnlock( (Handle) prefHdl);
  187.     FSClose( dRefNum);
  188.     if ( err != noErr) {
  189.         xFSpDelete(&aSpec);
  190.     }
  191.     return ( err);
  192.  
  193. }
  194.  
  195. pascal OSErr _ReadPreferences(PreferencesHdl *PreferencesHandle, Str31 filename)
  196. {
  197.     OSErr            err;
  198.     FSSpec            aSpec;
  199.     short            versionNumber;
  200.     short            dRefNum = 0;
  201.     PreferencesHdl    prefHdl = nil;
  202.     long            count;
  203.     
  204.     *PreferencesHandle = nil;
  205.  
  206.     // Get the preferences file name from disk.
  207.     err = GetPreferencesFileName( &aSpec, filename);
  208.     if ( err != noErr)
  209.         return ( err);
  210.         
  211.     // Open the data fork of the preferences file if it exists.
  212.     err = xFSpOpenDF(&aSpec, fsRdPerm, &dRefNum);
  213.  
  214.     if (err != noErr)  {
  215.         // This isn't really an 'error' as such
  216.         // ShowStrNum("\pFSpOpenDF error while opening preferences file ", err);
  217.         dRefNum = 0;    // To be safe
  218.         goto createDefaultPrefs;
  219.     }
  220.         
  221.     // Get the version number of the file.
  222.     count = sizeof(versionNumber);
  223.     err =  FSRead(dRefNum, &count, &versionNumber);
  224.     if (err != noErr) {
  225.         ShowStrNum("\pFSRead error while reading version number ", err);
  226.         goto createDefaultPrefs;
  227.     }
  228.  
  229.     prefHdl = (PreferencesHdl) NewHandleSys( sizeof(struct Preferences));
  230.     if ( prefHdl == nil)  {
  231.         err = MemError();
  232.         FSClose( dRefNum);
  233.         return( err);
  234.     }
  235.  
  236.     switch (versionNumber) {
  237.                     
  238.         case kCurrentVersion :
  239.             
  240.             count = sizeof(struct Preferences);
  241.             err = FSRead( dRefNum, &count, (Ptr) *prefHdl);
  242.             
  243.             // Check for a read error or not enough data read in.
  244.             if ( err != noErr) {
  245.                 ShowStrNum("\pFSRead error while reading Preferences data from disk ", err);
  246.                 goto createDefaultPrefs;
  247.             }
  248.  
  249.             if (count != sizeof(struct Preferences)) {
  250.                 ShowStrNum("\pFSRead error reading Preferences. Count should be", sizeof(struct Preferences));
  251.                 ShowStrNum("\pCount is", count);
  252.                 goto createDefaultPrefs;
  253.             }
  254.             
  255.             FSClose( dRefNum);
  256.             dRefNum = 0;    // To be safe
  257.  
  258.             
  259.             break;
  260.             
  261.         // Unrecognized version number. Don't take chances; create a new one.
  262.         default: 
  263.             goto createDefaultPrefs;
  264.             break;
  265.  
  266.     }
  267.     
  268.     *PreferencesHandle = prefHdl;
  269.  
  270.  
  271.     return (err);
  272.  
  273. // This label is reached if there is a recoverable problem: the preferences
  274. // file version is incorrect or unrecognized, or not all the data was read.
  275. // In any case, we close the old file (if open), then delete it as we're
  276. // going to create a new one anyway
  277.  
  278. createDefaultPrefs:
  279.     if ( prefHdl != nil) {
  280.         DisposeHandle( (Handle) prefHdl);
  281.         prefHdl = nil;
  282.     }
  283.     
  284.     if ( dRefNum != 0) {
  285.         FSClose( dRefNum);
  286.         dRefNum = 0;
  287.     }
  288.     err = xFSpDelete(&aSpec);
  289.     
  290.     // Create a new Preferences handle.
  291.     count = sizeof(struct Preferences);
  292.     prefHdl = (PreferencesHdl) NewHandleSys( count);
  293.     if ( prefHdl == nil)  {
  294.         err = MemError();
  295.         ShowStrNum("\pNewHandleSys is nil when creating new Preferences handle. ", err);
  296.         return ( err);
  297.     }
  298.  
  299.     
  300.     HLock( (Handle) prefHdl);
  301.     
  302.     // Fill in the defaults.
  303.     (**prefHdl).on_off             = false;
  304.     (**prefHdl).onlyPlayOne     = true;
  305.     (**prefHdl).iconAtStartup     = true;
  306.     (**prefHdl).animate             = true;
  307.     (**prefHdl).theText[0]         = 0;
  308.     (void) MakeVoiceSpec('????', '????', &(**prefHdl).theVoice);
  309.     (**prefHdl).theRate            = 0.0;
  310.     (**prefHdl).thePitch        = 0.0;
  311.  
  312.     HUnlock( (Handle) prefHdl);
  313.  
  314.     // Write the handle data to the Preferences file (it locks/unlocks it and
  315.     // creates the file if needed)
  316.     err =  WriteToPrefs( prefHdl, filename);
  317.     
  318.     if ( err == noErr) {
  319.         *PreferencesHandle = prefHdl;
  320.     }
  321.     else {
  322.         DisposeHandle( (Handle) prefHdl);
  323.     }
  324.     
  325.     return ( err);
  326. }
  327.  
  328. pascal OSErr xFSpDelete(const FSSpec *spec)
  329. {
  330.     long gestaltResult;
  331.     short err;
  332.     
  333.     err = Gestalt(gestaltFSAttr, &gestaltResult);
  334.     
  335.     if (err == noErr && (gestaltResult & (1 << gestaltHasFSSpecCalls)))
  336.     {
  337.         return FSpDelete(spec);
  338.     } else
  339.     {
  340.         HParamBlockRec hpb;
  341.         
  342.         zeroMemory((Ptr)&hpb, sizeof(HParamBlockRec));
  343.         specToHParamBlock(spec, &hpb);
  344.         return PBHDelete(&hpb, false);
  345.     }
  346. }
  347.  
  348. pascal OSErr xFSpCreate(const FSSpec *spec,OSType creator, OSType fileType, 
  349.     ScriptCode scriptTag)
  350. {
  351.     long gestaltResult;
  352.     short err;
  353.     
  354.     err = Gestalt(gestaltFSAttr, &gestaltResult);
  355.     
  356.     if (err == noErr && (gestaltResult & (1 << gestaltHasFSSpecCalls)))
  357.     {
  358.         return FSpCreate(spec, creator, fileType, scriptTag);
  359.     } else
  360.     {
  361.         return sys6Create(spec,creator,fileType);
  362.     }
  363. }
  364.  
  365. pascal OSErr xFSpCreateResFile(const FSSpec *spec,OSType creator,OSType fileType,
  366.     ScriptCode scriptTag)
  367. {
  368.     long gestaltResult;
  369.     short err;
  370.     
  371.     err = Gestalt(gestaltFSAttr, &gestaltResult);
  372.     
  373.     if (err == noErr && (gestaltResult & (1 << gestaltHasFSSpecCalls)))
  374.     {
  375.         FSpCreateResFile(spec, creator, fileType, scriptTag);
  376.         return ResError();
  377.     } else
  378.     {
  379.         return sys6Create(spec,creator,fileType);
  380.     }
  381. }
  382.  
  383. pascal OSErr xFSpOpenDF(const FSSpec *spec,char permission,short *refNum)
  384. {
  385.     long gestaltResult;
  386.     short err;
  387.     OSErr openErr;
  388.     
  389.     err = Gestalt(gestaltFSAttr, &gestaltResult);
  390.     
  391.     if (err == noErr && (gestaltResult & (1 << gestaltHasFSSpecCalls)))
  392.     {
  393.         return FSpOpenDF(spec, permission, refNum);
  394.     } else
  395.     {
  396.         HParamBlockRec hpb;
  397.         
  398.         zeroMemory((Ptr)&hpb, sizeof(HParamBlockRec));
  399.         specToHParamBlock(spec, &hpb);
  400.         hpb.ioParam.ioPermssn = permission;
  401.         hpb.ioParam.ioMisc = NULL;
  402.         openErr = PBHOpen(&hpb, false);
  403.         *refNum = hpb.ioParam.ioRefNum;
  404.         return openErr;
  405.     }
  406. }
  407.  
  408.  
  409. /*
  410.     specToHParamBlock
  411.     
  412.     Moves the information from the FSSpec record to the appropriate fields of the 
  413.     paramblock record.
  414.     
  415. */
  416. static void specToHParamBlock(const FSSpec *spec, HParmBlkPtr hpb)
  417. {
  418.     hpb->ioParam.ioVRefNum = spec->vRefNum;
  419.     hpb->fileParam.ioDirID = spec->parID;
  420.     hpb->ioParam.ioNamePtr = (unsigned char *)spec->name;
  421. }
  422.  
  423. static void zeroMemory(Ptr d,long len)  
  424. {
  425.     char *p = d;
  426.     
  427.     if(p != NULL) {
  428.         while(len-- > 0)
  429.             *p++ = 0;
  430.     }
  431. }
  432.  
  433. OSErr sys6Create(const FSSpec *spec,OSType creator,OSType fileType)
  434. {
  435.     short err;
  436.     HParamBlockRec hpb;
  437.     
  438.     zeroMemory((Ptr)&hpb, sizeof(HParamBlockRec));
  439.     specToHParamBlock(spec, &hpb);
  440.     err = PBHCreate(&hpb, false);
  441.     if (err == noErr)
  442.     {
  443.         zeroMemory((Ptr)&hpb, sizeof(HParamBlockRec));
  444.         specToHParamBlock(spec, &hpb);
  445.         err = PBHGetFInfo(&hpb, false);
  446.         if (err == noErr)
  447.         {
  448.             specToHParamBlock(spec, &hpb);
  449.             hpb.fileParam.ioFlFndrInfo.fdType = fileType;
  450.             hpb.fileParam.ioFlFndrInfo.fdCreator = creator;
  451.             err = PBHSetFInfo(&hpb, false);
  452.             if (err == noErr)
  453.             {
  454.                 ParamBlockRec pb;
  455.                 
  456.                 zeroMemory((Ptr)&pb, sizeof(HParamBlockRec));
  457.                 pb.ioParam.ioVRefNum = spec->vRefNum;
  458.                 PBFlushVol(&pb, false);
  459.             }
  460.         }
  461.     }
  462.     return err;
  463. }
  464.  
  465.